package com.xp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xp.entity.Menu;
import com.xp.mapper.MenuMapper;
import com.xp.service.MenuService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜单服务实现类
 * 
 * @author xp
 * @since 2024-01-01
 */
@Service
@RequiredArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    private static final Logger log = LoggerFactory.getLogger(MenuServiceImpl.class);

    private final MenuMapper menuMapper;

    /**
     * 分页查询菜单列表
     */
    @Override
    public IPage<Menu> getMenuPage(Page<Menu> page, String name, Integer status) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        if (StringUtils.hasText(name)) {
            queryWrapper.like(Menu::getName, name);
        }
        if (status != null) {
            queryWrapper.eq(Menu::getStatus, status);
        }
        
        // 按排序字段和创建时间排序
        queryWrapper.orderByAsc(Menu::getSort).orderByDesc(Menu::getCreateTime);
        
        return menuMapper.selectPage(page, queryWrapper);
    }

    /**
     * 根据父级菜单ID查询子菜单列表
     */
    @Override
    public List<Menu> getMenusByParentId(Long parentId) {
        return menuMapper.selectByParentId(parentId);
    }

    /**
     * 查询所有启用的菜单
     */
    @Override
    public List<Menu> getEnabledMenus() {
        return menuMapper.selectEnabledMenus();
    }

    /**
     * 查询所有菜单
     */
    @Override
    public List<Menu> getAllMenus() {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(Menu::getSort).orderByDesc(Menu::getCreateTime);
        return list(queryWrapper);
    }

    /**
     * 根据菜单类型查询菜单列表
     */
    @Override
    public List<Menu> getMenusByType(Integer type) {
        return menuMapper.selectByType(type);
    }

    /**
     * 构建菜单树
     */
    @Override
    public List<Menu> buildMenuTree(List<Menu> menus) {
        List<Menu> tree = new ArrayList<>();
        
        // 找出所有根节点（parentId为null或0）
        List<Menu> rootMenus = menus.stream()
                .filter(menu -> menu.getParentId() == null || menu.getParentId() == 0)
                .collect(Collectors.toList());
        
        // 为每个根节点构建子树
        for (Menu rootMenu : rootMenus) {
            buildChildren(rootMenu, menus);
            tree.add(rootMenu);
        }
        
        return tree;
    }

    /**
     * 递归构建子菜单
     */
    private void buildChildren(Menu parent, List<Menu> allMenus) {
        List<Menu> children = allMenus.stream()
                .filter(menu -> parent.getId().equals(menu.getParentId()))
                .sorted((m1, m2) -> {
                    // 按sort字段排序，如果sort相同则按创建时间倒序
                    int sortCompare = Integer.compare(
                        m1.getSort() != null ? m1.getSort() : 0,
                        m2.getSort() != null ? m2.getSort() : 0
                    );
                    if (sortCompare != 0) {
                        return sortCompare;
                    }
                    return m2.getCreateTime().compareTo(m1.getCreateTime());
                })
                .collect(Collectors.toList());
        
        if (!children.isEmpty()) {
            parent.setChildren(children);
            for (Menu child : children) {
                buildChildren(child, allMenus);
            }
        }
    }

    /**
     * 创建菜单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createMenu(Menu menu) {
        try {
            // 设置默认值
            if (menu.getStatus() == null) {
                menu.setStatus(1); // 默认启用
            }
            if (menu.getSort() == null) {
                menu.setSort(0);
            }
            menu.setCreateTime(LocalDateTime.now());
            menu.setUpdateTime(LocalDateTime.now());
            
            return save(menu);
        } catch (Exception e) {
            log.error("创建菜单失败", e);
            return false;
        }
    }

    /**
     * 更新菜单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMenu(Menu menu) {
        try {
            menu.setUpdateTime(LocalDateTime.now());
            return updateById(menu);
        } catch (Exception e) {
            log.error("更新菜单失败，菜单ID: {}", menu.getId(), e);
            return false;
        }
    }

    /**
     * 删除菜单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteMenu(Long id) {
        try {
            // 检查是否有子菜单
            List<Menu> children = getMenusByParentId(id);
            if (!children.isEmpty()) {
                log.warn("菜单存在子菜单，无法删除，菜单ID: {}", id);
                return false;
            }
            
            return removeById(id);
        } catch (Exception e) {
            log.error("删除菜单失败，菜单ID: {}", id, e);
            return false;
        }
    }

    /**
     * 切换菜单状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean toggleMenuStatus(Long id, Integer status) {
        try {
            Menu menu = new Menu();
            menu.setId(id);
            menu.setStatus(status);
            menu.setUpdateTime(LocalDateTime.now());
            
            return updateById(menu);
        } catch (Exception e) {
            log.error("切换菜单状态失败，菜单ID: {}, 状态: {}", id, status, e);
            return false;
        }
    }
}